package com.tqyan.service.transfer;

import com.alibaba.fastjson.JSONObject;
import com.tqyan.model.HttpClientResult;
import com.tqyan.model.controller.request.OpenAIChatRequest;
import com.tqyan.model.controller.request.OpenAIDrawRequest;
import com.tqyan.model.controller.response.OpenAIChatResp;
import com.tqyan.model.controller.response.OpenAIDrawResp;
import com.tqyan.model.enums.ChatCreativeAbilityEnum;
import com.tqyan.model.enums.GPTModelEnum;
import com.tqyan.model.enums.GPTRoleEnum;
import com.tqyan.model.exp.DefaultException;
import com.tqyan.service.service.ICallBack;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @description OpenAI服务
 * <p> <功能详细描述> </p>
 *
 * @author 陈晨
 * @date 2023/4/12 15:44
 */
@Component
@Slf4j
public class OpenAIService {
//    private static final String KEY= "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";
    private static final String KEY= "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";
    /** 聊天URL */
    public static final String URL_CHAT = "https://api.openai.com/v1/chat/completions";
    /** 绘画URL */
    public static final String DRAW_CHAT = "https://api.openai.com/v1/images/generations";

    @Autowired
    private HttpClientService httpClientService;

    /**
     * @description 聊天请求
     * <p>
     * {
     *   "model": "gpt-3.5-turbo",
     *   "messages": [{"role": "user", "content": "Hello!"}]
     * }
     *
     * {
     *   "id": "chatcmpl-123",
     *   "object": "chat.completion",
     *   "created": 1677652288,
     *   "choices": [{
     *     "index": 0,
     *     "message": {
     *       "role": "assistant",
     *       "content": "\n\nHello there, how may I assist you today?",
     *     },
     *     "finish_reason": "stop"
     *   }],
     *   "usage": {
     *     "prompt_tokens": 9,
     *     "completion_tokens": 12,
     *     "total_tokens": 21
     *   }
     * }
     * </p>
     *
     * @author 陈晨
     * @date 2023/4/12 17:01
     */
    public OpenAIChatResp requestChatComplete(OpenAIChatRequest chatRequest) {
        try {
            Map<String, String> headers = new HashMap<>();
            headers.put("Accept", "*/*");
            headers.put("Accept-Encoding", "gzip, deflate, br");
            headers.put("Connection", "keep-alive");
            headers.put("Content-Type", "application/json");
            headers.put("Authorization", "Bearer " + KEY);
            HttpClientResult result = httpClientService.doPost(URL_CHAT, headers, null
                    , OpenAIChatRequest.getRequestBody(chatRequest), StandardCharsets.UTF_8);
            if (result.getCode() != 200) {
                throw new DefaultException(result.getContent());
            }
            return JSONObject.parseObject(result.getContent(), OpenAIChatResp.class);
        } catch (Exception e) {
            log.error("[OpenAI] chatRequest={}, 聊天请求异常: {}", chatRequest, e.getMessage(), e);
            throw new DefaultException("502", e.getMessage());
        }
    }

    /**
     * @description 聊天请求, 流响应
     * <p> <功能详细描述> </p>
     *
     * @author 陈晨
     * @date 2023/4/13 16:49
     */
    public void requestChatStream(OpenAIChatRequest chatRequest, ICallBack<String> callback) {
        chatRequest.setStream(true);
        InputStream input = null;
        BufferedReader bufferedReader = null;
        try {
            Map<String, String> headers = new HashMap<>();
            headers.put("Accept", "*/*");
            headers.put("Accept-Encoding", "gzip, deflate, br");
            headers.put("Connection", "keep-alive");
            headers.put("Content-Type", "application/json");
            headers.put("Authorization", "Bearer " + KEY);
            input = httpClientService.getResponseStreamByPost(URL_CHAT, headers, null
                    , OpenAIChatRequest.getRequestBody(chatRequest));
            bufferedReader = new BufferedReader(new InputStreamReader(input));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                callback.handle(line);
            }
        } catch (Exception e) {
            log.error("[OpenAI] chatRequest={}, 聊天-流响应请求异常: {}", chatRequest, e.getMessage(), e);
            throw new DefaultException("502", e.getMessage());
        } finally {
            try {
                if (null != bufferedReader) {
                    bufferedReader.close();
                }
                if (null != input) {
                    input.close();
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    /**
     * @description 获取关键词
     * <p> <功能详细描述> </p>
     *
     * @author 陈晨
     * @date 2023/4/20 18:36
     */
    @Deprecated
    public String getKeywords(String content, int min, int max) {
//        return "Java, 入门, 前途, 优秀, 工程师."
//                .replaceAll("，", ",")
//                .replaceAll("。", ".")
//                .replaceAll("\\.", "")
//                .replaceAll(" ", "");

        // 请求GPT, 流响应
        long startTime = System.currentTimeMillis();
        OpenAIChatRequest chatRequest = new OpenAIChatRequest();
        chatRequest.setModel(GPTModelEnum.GPT_3_5.getValue());
        chatRequest.setTemperature(1.0);
        chatRequest.addMessage(GPTRoleEnum.USER.getValue()
                , "提取以下内容" + min + "-" + max + "个关键词用逗号分割：" + content);
        final boolean[] isException = {false};
        AtomicBoolean isComplete = new AtomicBoolean(false);
        StringBuilder result = new StringBuilder();
        this.requestChatStream(chatRequest, data -> {
            if (StringUtils.isBlank(data) || isComplete.get()) {
                return;
            }
            // 响应异常
            if (isException[0] || data.indexOf("data: ") != 0) {
                isException[0] = true;
                return;
            }
            OpenAIChatResp chatResp = JSONObject.parseObject(data.substring(6), OpenAIChatResp.class);
            // 答案完成
            if ("stop".equals(chatResp.getChoices().get(0).getFinish_reason())) {
                isComplete.set(true);
                return;
            }
            // 追加内容
            if (StringUtils.isBlank(chatResp.getChoices().get(0).getDelta().getRole())) {
                String appendContent = chatResp.getChoices().get(0).getDelta().getContent();
                result.append(appendContent);
                log.info("[OpenAI] gptId={}, appendContent={}, 获取关键词, 追加内容: {}"
                        , chatResp.getId(), appendContent, result);
            }
        });
        long endTime = System.currentTimeMillis();
        // GPT请求异常
        if (isException[0]) {
            log.info("[OpenAI] content={}, min={}, max={}, GPT请求异常: {}, 耗时: {}ms"
                    , content, min, max, result, endTime - startTime);
            return "";
        }
        String keywords = result.toString()
                .replaceAll("、", ",")
                .replaceAll("，", ",")
                .replaceAll("。", ".")
                .replaceAll("\\.", "")
                .replaceAll(" ", "");
        log.info("[OpenAI] content={}, min={}, max={}, keywords={}, 请求GPT, 耗时: {}ms"
                , content, min, max, keywords, endTime - startTime);
        return keywords;
    }

    /**
     * @description 绘画请求
     * <p>
     *   {
     *     "prompt": "A cute baby sea otter",
     *     "n": 2,
     *     "size": "1024x1024"
     *   }
     *
     *   {
     *     "created": 1681452046,
     *     "data": [
     *         {
     *             "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/org-34fKcGR8UN2fEkwAPL9HJuWH/user-dj4j55J6yo0Sdb1ecC28u5To/img-uJCr0PSQYL3d4e9xvqo4w1zN.png?st=2023-04-14T05%3A00%3A46Z&se=2023-04-14T07%3A00%3A46Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-04-13T17%3A15%3A37Z&ske=2023-04-14T17%3A15%3A37Z&sks=b&skv=2021-08-06&sig=NSFvq9l0u%2BhQg%2BMim/Kke%2BTmiJP3oqQdg2AfbriKbyw%3D"
     *         }
     *     ]
     *   }
     *
     * </p>
     *
     * @author 陈晨
     * @date 2023/4/14 13:41
     */
    public OpenAIDrawResp requestDraw(OpenAIDrawRequest drawRequest) {
        try {
            Map<String, String> headers = new HashMap<>();
//            headers.put("Accept", "*/*");
//            headers.put("Accept-Encoding", "gzip, deflate, br");
//            headers.put("Connection", "keep-alive");
            headers.put("Content-Type", "application/json");
            headers.put("Authorization", "Bearer " + KEY);
            HttpClientResult result = httpClientService.doPost(DRAW_CHAT, headers, null
                    , OpenAIDrawRequest.getRequestBody(drawRequest), null);
            log.info("[OpenAI] drawRequest={}, 绘画请求响应: {}", drawRequest, JSONObject.toJSONString(result));
            if (result.getCode() != 200) {
                throw new DefaultException(result.getContent());
            }
            return JSONObject.parseObject(result.getContent(), OpenAIDrawResp.class);
        } catch (Exception e) {
            log.error("[OpenAI] drawRequest={}, 绘画请求异常: {}", drawRequest, e.getMessage(), e);
            throw new DefaultException("502", e.getMessage());
        }
    }

    public static void main(String[] args) throws Exception {
        OpenAIChatRequest request = new OpenAIChatRequest();
        request.setModel(GPTModelEnum.GPT_3_5.getValue());
        request.setTemperature(ChatCreativeAbilityEnum.TEMPERATURE_1_0.getTemperature() / 10D);
        request.setStream(true);
        request.addMessage(GPTRoleEnum.USER.getValue(), "给我一个启发");

        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建http对象
        HttpPost httpPost = new HttpPost(URL_CHAT);
        StringEntity entity = new StringEntity(OpenAIChatRequest.getRequestBody(request)
                , ContentType.APPLICATION_JSON);
        httpPost.setEntity(entity);
//        // 设置请求头
//        this.packageHeader(headers, httpPost);
//        // 设置请求参数
//        this.packageParam(params, httpPost);
//        if (StringUtils.isNotBlank(requestBody)) {
//            httpPost.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON));
//        }
        // 执行请求并获得响应结果
        HttpResponse httpResponse = httpClient.execute(httpPost);
        InputStream inputStream = httpResponse.getEntity().getContent();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        log.info("=========================================");
        while ((line = bufferedReader.readLine()) != null) {
            log.info(line);
        }
        log.info("=========================================");
    }

}


